home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Almathera Ten Pack 2: CDPD 1
/
Almathera Ten on Ten - Disc 2: CDPD 1.iso
/
pd
/
351-375
/
362
/
puzz
/
source
/
audio.c
next >
Wrap
C/C++ Source or Header
|
1995-03-14
|
6KB
|
289 lines
/* audio.c Martin Round November '89
This code is taken straight from Steven A. Bennett's 'scales.c'
Thanks Steven!
I've mostly left the code in it's original state, only putting in
a few function prototypes and 'voids' to stop my compiler issuing
me with warnings.
I've also stripped comments and altered bracket indenting into my own
weird style - sorry Steven! Actually it's not my own style, I'm driven
to use it by a stupid Lint-like program I use called 'ccheck'.
*/
#define PRIORITY 10L
#define NBR_IOA_STRUCTS 10L
#define PV_IOA_STRUCT 0L
#define FIN_IOA_STRUCT 9L
#define BIG_WAVE 256L
#define NBR_WAVES 7L
#define WAVES_TOTAL 1024L
#define YES 1L
#define NO 0L
extern struct MsgPort *CreatePort();
extern void *AllocMem();
void clear_audio (int);
UBYTE aMap[] = { 0x0f };
long voiceMap[] = { 1, 2, 4, 8 };
struct IOAudio *ioa, *finishioa, *ioapv;
struct IOAudio *ioainuse[4];
struct IOAudio *freeioa[4];
long unitno = 1;
int error;
int waiting[4] = { NO, NO, NO, NO };
int woffsets[] =
{ 0, 256, 384, 448, 480, 496, 504, 508, 510 };
int wlen[] =
{ 256, 128, 64, 32, 16, 8, 4, 2, 1 };
int perval[] =
{ 428, 404, 381, 360, 339, 320, 302, 285, 269, 254, 240, 226, 214 };
BYTE *wptr;
BYTE *owptr[4] = { NULL, NULL, NULL, NULL };
char *portstring[] =
{
"Audio one",
"Audio two",
"Audio three",
"Audio four",
"Audio five",
"Audio six",
"Audio seven",
"Audio eight"
};
int get_audio()
{
int i;
ioa = (struct IOAudio *)
AllocMem((NBR_IOA_STRUCTS * (long)sizeof(*ioa)),MEMF_PUBLIC | MEMF_CLEAR);
if (ioa == NULL)
{
clear_audio(1);
return(0);
}
for (i = 0; i < 4; ++i)
{
ioainuse[i] = &ioa[i + 1];
freeioa[i] = &ioa[i + 5];
}
ioapv = &ioa[PV_IOA_STRUCT];
finishioa = &ioa[FIN_IOA_STRUCT];
ioa->ioa_Request.io_Message.mn_Node.ln_Pri = PRIORITY;
ioa->ioa_Request.io_Message.mn_ReplyPort =
CreatePort("Audio zero", 0L);
if (ioa->ioa_Request.io_Message.mn_ReplyPort == NULL)
{
clear_audio(2);
return(0);
}
ioa->ioa_Data = aMap;
ioa->ioa_Length = (long)sizeof(aMap);
error = OpenDevice(AUDIONAME, 0L, (struct ioRequest *) ioa, 0L);
if (error)
{
clear_audio(3);
return(0);
}
*finishioa = *ioa;
finishioa->ioa_Request.io_Flags = IOF_QUICK;
ioapv->ioa_Request.io_Flags = IOF_QUICK;
finishioa->ioa_Request.io_Command = ADCMD_FINISH;
ioapv->ioa_Request.io_Command = ADCMD_PERVOL;
for (i = 0; i < 4; ++i)
{
*freeioa[i] = *ioa;
*ioainuse[i] = *ioa;
freeioa[i]->ioa_Request.io_Message.mn_ReplyPort =
CreatePort(portstring[i], 0L);
ioainuse[i]->ioa_Request.io_Message.mn_ReplyPort =
CreatePort(portstring[i + 4], 0L);
}
for (i = 0; i < 4; ++i)
if
(
freeioa[i]->ioa_Request.io_Message.mn_ReplyPort == NULL ||
ioainuse[i]->ioa_Request.io_Message.mn_ReplyPort == NULL
)
{
clear_audio(4);
return (0);
}
return (makewaves());
}
void clear_audio(finishcode)
int finishcode;
{
int i;
switch(finishcode)
{
case 0:
FreeMem(wptr, WAVES_TOTAL);
case 4:
case 5:
for (i = 0; i < 4; ++i)
{
if (freeioa[i]->ioa_Request.io_Message.mn_ReplyPort)
DeletePort(freeioa[i]->ioa_Request.io_Message.mn_ReplyPort);
if (ioainuse[i]->ioa_Request.io_Message.mn_ReplyPort)
DeletePort(ioainuse[i]->ioa_Request.io_Message.mn_ReplyPort);
}
CloseDevice((struct ioRequest *) ioa);
case 3:
DeletePort(ioa->ioa_Request.io_Message.mn_ReplyPort);
case 2:
FreeMem(ioa, (NBR_IOA_STRUCTS * (long)sizeof(*ioa)));
}
}
void setwpv(wf, len, per, vol, voice)
char *wf;
int len, per, vol, voice;
{
struct IOAudio *tmpioa;
freeioa[voice]->ioa_Request.io_Command = CMD_WRITE;
freeioa[voice]->ioa_Request.io_Flags = ADIOF_PERVOL | IOF_QUICK;
freeioa[voice]->ioa_Cycles = 0;
freeioa[voice]->ioa_Request.io_Unit = (struct Unit *)unitno;
finishioa->ioa_Request.io_Unit = (struct Unit *)unitno;
freeioa[voice]->ioa_Data = (UBYTE *)wf;
freeioa[voice]->ioa_Length = len;
freeioa[voice]->ioa_Period = per;
freeioa[voice]->ioa_Volume = vol;
if (waiting[voice])
{
BeginIO((struct ioRequest *) finishioa);
WaitIO((struct ioRequest *) ioainuse[voice]);
waiting[voice] = NO;
}
BeginIO((struct ioRequest *) freeioa[voice]);
error = CheckIO((struct ioRequest *) freeioa[voice]);
if (error)
WaitIO((struct ioRequest *) freeioa[voice]);
waiting[voice] = YES;
tmpioa = ioainuse[voice];
ioainuse[voice] = freeioa[voice];
freeioa[voice] = tmpioa;
}
void setpv(per, vol)
int per, vol;
{
ioapv->ioa_Period = per;
ioapv->ioa_Volume = vol;
ioapv->ioa_Request.io_Unit = (struct Unit *)unitno;
BeginIO((struct ioRequest *) ioapv);
}
void StopVoices()
{
int voice;
for (voice = 0; voice < 4; ++voice)
{
if (waiting[voice])
{
unitno = voiceMap[voice];
setpv(128, 0);
finishioa->ioa_Request.io_Unit = (struct Unit *)unitno;
BeginIO((struct ioRequest *) finishioa);
WaitIO((struct ioRequest *) ioainuse[voice]);
waiting[voice] = NO;
}
}
}
void setwave(wfp)
UBYTE *wfp;
{
int i;
for (i = 0; i < BIG_WAVE; ++i)
wfp[i] = i;
}
void xpandwave(wfp)
BYTE *wfp;
{
int i, j, rate;
BYTE *tptr;
rate = 1;
tptr = wfp + BIG_WAVE;
for (i = 0; i < NBR_WAVES - 1; ++i)
{
rate *= 2;
for (j = 0; j < BIG_WAVE; j += rate)
*tptr++ = wfp[j];
}
}
int makewaves()
{
wptr = (BYTE *)AllocMem(WAVES_TOTAL, MEMF_CHIP);
if (wptr == NULL)
{
clear_audio(5);
return (0);
}
setwave(wptr);
xpandwave(wptr);
return (1);
}
void play_note(note, voice)
int note, voice;
{
int per, oct;
BYTE *wfp;
unitno = voiceMap[voice];
if (note >= 100)
{
if (waiting[voice])
setpv(200, 0);
return;
}
oct = note / 12;
per = perval[note % 12];
wfp = wptr + woffsets[oct];
if (wfp == owptr[voice])
setpv(per, 32);
else
{
setwpv(wfp, wlen[oct], per, 32, voice);
owptr[voice] = wfp;
}
}